from datetime import timedelta

from fastapi import HTTPException, status
from sqlalchemy.orm import joinedload

from server.controller.log import create_log
from server.core.security import create_access_token
from server.db.models.system import User, Role, Menu
from server.schemas import permission
from utils.password_validate import password_validate
from utils.security import verify_password


def handler_user_info(query_set):
    user_data = dict()
    for query in query_set:
        # 构建用户基本信息
        user_data.update({
            "id": query.id,
            "username": query.username,
            "real_name": query.real_name,
            "phone": query.phone,
            "is_active": query.is_active,
            "is_superuser": query.is_superuser,
            "avatar": query.avatar,
            "role_list": []
        })

        # 处理每个权限及其关联菜单
        for role in query.roles:
            role_data = {
                "id": role.id,
                "name": role.name,
                "code": role.code,
                "description": role.description,
                "menu_list": [{
                    "name": menu.name,
                    "path": menu.path,
                    "icon": menu.icon,
                    "order": menu.order,
                    "permission":  menu.permission,
                } for menu in role.menus]
            }
            user_data["role_list"].append(role_data)

    return user_data




def user_login(request, loginDate, db):
    """
    登录接口
    :param request:
    :param loginDate:
    :param db:
    :return:
    """

    user_exist = db.query(User).filter(User.username == loginDate.username and User.is_deleted == False).first()
    if not user_exist:
        create_log(
            db=db,
            method=request.method,
            path=str(request.url),
            params=str(request.path_params),
            ip_address=request.client.host,
            status_code=1400,
            user_agent=request.headers.get("User-Agent"),
            response="用户名或密码不正确，请重新输入"
        )
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "code": 1400,
            }
        )

    if not user_exist.is_active:
        create_log(
            db=db,
            user_id=user_exist.id,
            method=request.method,
            path=str(request.url),
            params=str(request.path_params),
            ip_address=request.client.host,
            status_code=1401,
            user_agent=request.headers.get("User-Agent"),
            response="用户未激活"
        )
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail={
                "code": 1401,
                "msg": "用户未激活"
            }
        )
    validate_passwd = password_validate(loginDate.password)
    if not validate_passwd:
        create_log(
            db=db,
            user_id=user_exist.id,
            method=request.method,
            path=str(request.url),
            params=str(request.path_params),
            ip_address=request.client.host,
            status_code=1402,
            user_agent=request.headers.get("User-Agent"),
            response="密码长度大于8且必须为数值、大小写字母、特殊字符组合"
        )
        raise HTTPException(
            status_code=status.HTTP_402_PAYMENT_REQUIRED,
            detail={
                "code": 1402,
                "msg": "密码长度大于8且必须为数值、大小写字母、特殊字符组合"
            }
        )

    verify_pwd = verify_password(loginDate.password, user_exist.password)
    if verify_pwd == False:
        create_log(
            db=db,
            user_id=user_exist.id,
            method=request.method,
            path=str(request.url),
            params=str(request.path_params),
            ip_address=request.client.host,
            status_code=1400,
            user_agent=request.headers.get("User-Agent"),
            response="用户名或密码不正确，请重新输入"
        )
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "code": 1400,
                "msg": "用户名或密码不正确，请重新输入"
            }
        )
    else:
        token_expire = timedelta(minutes=60)
        assess_token = create_access_token(
            data={"id": user_exist.id, "username": user_exist.username}, expires_delta=token_expire
        )
        if user_exist.is_superuser:
            superuser_info = {
                "id": user_exist.id,
                "username": user_exist.username,
                "real_name": user_exist.real_name,
                "phone": user_exist.phone,
                "avatar": user_exist.avatar,
                "is_active": user_exist.is_active,
                "is_superuser": user_exist.is_superuser,
            }
            create_log(
                db=db,
                user_id=user_exist.id,
                method=request.method,
                path=str(request.url),
                params=str(request.path_params),
                ip_address=request.client.host,
                status_code=200,
                user_agent=request.headers.get("User-Agent"),
                response="登录成功"
            )
            return {
                "data": superuser_info,
                "token": assess_token,
                "code": 200,
                "msg": "登录成功"
            }
        else:
            user_infos = db.query(User).options(
                joinedload(User.roles).joinedload(Role.menus)
            ).filter(
                User.username == user_exist.username,
            ).all()

            user_info = handler_user_info(user_infos)

            create_log(
                db=db,
                user_id=user_exist.id,
                method=request.method,
                path=str(request.url),
                params=str(request.path_params),
                ip_address=request.client.host,
                status_code=200,
                user_agent=request.headers.get("User-Agent"),
                response="登录成功"
            )
            return {
                "data": user_info,
                "token": assess_token,
                "code": 200,
                "msg": "登录成功"
                }